package com.neuronbit.businessflow.intellij.lang;

import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayFactory;
import com.neuronbit.businessflow.intellij.BpmFileType;
import com.neuronbit.businessflow.intellij.BpmLanguage;
import com.neuronbit.businessflow.intellij.antlr.BpmParser;
import org.antlr.intellij.adaptor.lexer.RuleIElementType;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * The type Psi bpm file.
 */
public class PsiBpmFile extends PsiFileBase/* implements ScopeNode*/ {
    /**
     * Instantiates a new Psi bpm file.
     *
     * @param viewProvider the view provider
     */
    protected PsiBpmFile(@NotNull FileViewProvider viewProvider) {
        super(viewProvider, BpmLanguage.INSTANCE);
    }

    @Override
    public @NotNull FileType getFileType() {
        return BpmFileType.INSTANCE;
    }

//    @Override
//    public @Nullable PsiElement resolve(PsiNamedElement element) {
//        throw new UnsupportedOperationException("bpm psi file resolve is not implemented yet");
//    }

    /**
     * Get call psi element @ not null [ ].
     *
     * @return the psi element @ not null [ ]
     */
    public PsiElement @NotNull [] getCall() {
        List<PsiElement> elements = getCall(getFirstChild());
        return elements.toArray(new PsiElement[0]);
    }

    /**
     * Get attribute psi element @ not null [ ].
     *
     * @return the psi element @ not null [ ]
     */
    public PsiElement @NotNull [] getAttribute() {
        return new PsiElement[]{getFirstChild().getChildren()[3].getChildren()[3].getChildren()[2]};
    }

    /**
     * Gets call.
     *
     * @param element the element
     * @return the call
     */
    public List<PsiElement> getCall(PsiElement element) {
        IElementType elementType = element.getNode().getElementType();
        if (elementType instanceof RuleIElementType && ((RuleIElementType) elementType).getRuleIndex() == BpmParser.RULE_callDef) {
            return Collections.singletonList(element);
        } else {
            List<PsiElement> result = new ArrayList<>();
            for (PsiElement child : element.getChildren()) {
                result.addAll(getCall(child));
            }
            return result;
        }
    }

    /**
     * The Empty array.
     */
    PsiElement @NotNull [] EMPTY_ARRAY = new PsiElement[0];

    /**
     * The Array factory.
     */
    ArrayFactory<PsiElement> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PsiElement[count];
}
